Jackson একটি জনপ্রিয় Java লাইব্রেরি যা JSON ডেটা serialization এবং deserialization-এর জন্য ব্যবহৃত হয়। Complex validation scenarios হ্যান্ডল করার জন্য Jackson বিভিন্ন টুল এবং কাস্টম কৌশল প্রদান করে। এটি মূলত API-তে প্রাপ্ত JSON ডেটার বৈধতা যাচাই এবং সঠিকভাবে প্রক্রিয়াকরণের জন্য গুরুত্বপূর্ণ।
Complex Validation কেন গুরুত্বপূর্ণ?
- Dynamic Data Validation: JSON ডেটার কাঠামো এবং মান নির্ভুল কিনা তা নিশ্চিত করা।
- Custom Rules Implementation: কাস্টম validation rules প্রয়োগ করা।
- Error Reporting: ভুল JSON ডেটার জন্য যথাযথ ত্রুটি বার্তা প্রদান।
- Nested Structure Validation: জটিল এবং nested JSON স্ট্রাকচারের ডেটা যাচাই।
Validation-এর জন্য টুলস এবং পদ্ধতি
1. Annotations দিয়ে Validation
Java Bean Validation API (JSR-380) এর annotations ব্যবহার করে Jackson-এর মাধ্যমে সহজেই validation করা যায়।
Dependency (Hibernate Validator):
<dependency>
<groupId>org.hibernate.validator</groupId>
<artifactId>hibernate-validator</artifactId>
<version>8.0.0.Final</version>
</dependency>
উদাহরণ:
import jakarta.validation.constraints.NotNull;
import jakarta.validation.constraints.Size;
public class User {
@NotNull(message = "Name cannot be null")
@Size(min = 2, max = 50, message = "Name must be between 2 and 50 characters")
private String name;
@NotNull(message = "Email cannot be null")
private String email;
// Getters and Setters
public String getName() { return name; }
public void setName(String name) { this.name = name; }
public String getEmail() { return email; }
public void setEmail(String email) { this.email = email; }
}
Validation Integration:
import com.fasterxml.jackson.databind.ObjectMapper;
import jakarta.validation.Validation;
import jakarta.validation.Validator;
import jakarta.validation.ValidatorFactory;
public class AnnotationValidationExample {
public static void main(String[] args) {
try {
String json = """
{
"name": "John",
"email": null
}
""";
ObjectMapper mapper = new ObjectMapper();
User user = mapper.readValue(json, User.class);
// Validator তৈরি
ValidatorFactory factory = Validation.buildDefaultValidatorFactory();
Validator validator = factory.getValidator();
// Validate
var violations = validator.validate(user);
if (!violations.isEmpty()) {
violations.forEach(violation -> System.out.println(violation.getMessage()));
} else {
System.out.println("Valid User: " + user.getName());
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
আউটপুট:
Email cannot be null
2. Custom Deserialization-এর মাধ্যমে Validation
Custom deserialization ব্যবহার করে JSON ডেটা validate এবং প্রক্রিয়াকরণ করা যায়।
উদাহরণ:
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.DeserializationContext;
import com.fasterxml.jackson.databind.JsonDeserializer;
import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
import java.io.IOException;
class User {
private String name;
@JsonDeserialize(using = CustomEmailDeserializer.class)
private String email;
// Getters and Setters
public String getName() { return name; }
public void setName(String name) { this.name = name; }
public String getEmail() { return email; }
public void setEmail(String email) { this.email = email; }
}
class CustomEmailDeserializer extends JsonDeserializer<String> {
@Override
public String deserialize(JsonParser p, DeserializationContext ctxt) throws IOException, JsonProcessingException {
String email = p.getText();
if (email == null || !email.contains("@")) {
throw new IOException("Invalid email format: " + email);
}
return email;
}
}
ব্যবহার:
public class CustomDeserializerValidationExample {
public static void main(String[] args) {
try {
String json = """
{
"name": "John",
"email": "invalidEmail"
}
""";
ObjectMapper mapper = new ObjectMapper();
User user = mapper.readValue(json, User.class);
System.out.println("User: " + user.getName() + ", Email: " + user.getEmail());
} catch (Exception e) {
System.err.println("Validation Error: " + e.getMessage());
}
}
}
আউটপুট:
Validation Error: Invalid email format: invalidEmail
3. Custom Validator ব্যবহার
Custom Validator তৈরি করে জটিল validation নিয়ম প্রয়োগ করা যায়।
উদাহরণ:
import jakarta.validation.Constraint;
import jakarta.validation.Payload;
import jakarta.validation.ConstraintValidator;
import jakarta.validation.ConstraintValidatorContext;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
// Custom Annotation
@Constraint(validatedBy = PhoneNumberValidator.class)
@Target({ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
@interface ValidPhoneNumber {
String message() default "Invalid phone number";
Class<?>[] groups() default {};
Class<? extends Payload>[] payload() default {};
}
// Validator Implementation
class PhoneNumberValidator implements ConstraintValidator<ValidPhoneNumber, String> {
@Override
public boolean isValid(String phoneNumber, ConstraintValidatorContext context) {
return phoneNumber != null && phoneNumber.matches("\\d{10}");
}
}
Model Class:
public class Contact {
@ValidPhoneNumber
private String phoneNumber;
// Getters and Setters
public String getPhoneNumber() { return phoneNumber; }
public void setPhoneNumber(String phoneNumber) { this.phoneNumber = phoneNumber; }
}
ব্যবহার:
public class CustomValidatorExample {
public static void main(String[] args) {
Contact contact = new Contact();
contact.setPhoneNumber("12345");
ValidatorFactory factory = Validation.buildDefaultValidatorFactory();
Validator validator = factory.getValidator();
var violations = validator.validate(contact);
if (!violations.isEmpty()) {
violations.forEach(violation -> System.out.println(violation.getMessage()));
} else {
System.out.println("Valid Phone Number: " + contact.getPhoneNumber());
}
}
}
আউটপুট:
Invalid phone number
4. Nested Object Validation
Nested objects বা জটিল JSON স্ট্রাকচারের validation সহজে করা যায়।
উদাহরণ:
import jakarta.validation.Valid;
import jakarta.validation.constraints.NotNull;
public class Order {
@NotNull
private String orderId;
@Valid
@NotNull
private User user;
// Getters and Setters
public String getOrderId() { return orderId; }
public void setOrderId(String orderId) { this.orderId = orderId; }
public User getUser() { return user; }
public void setUser(User user) { this.user = user; }
}
Validation Integration:
public class NestedValidationExample {
public static void main(String[] args) {
try {
String json = """
{
"orderId": "123",
"user": {
"name": "John",
"email": null
}
}
""";
ObjectMapper mapper = new ObjectMapper();
Order order = mapper.readValue(json, Order.class);
ValidatorFactory factory = Validation.buildDefaultValidatorFactory();
Validator validator = factory.getValidator();
var violations = validator.validate(order);
if (!violations.isEmpty()) {
violations.forEach(violation -> System.out.println(violation.getMessage()));
} else {
System.out.println("Valid Order ID: " + order.getOrderId());
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
আউটপুট:
Email cannot be null
- Basic Validation: Annotations ব্যবহার করে সহজেই validation পরিচালনা করা যায়।
- Complex Validation: কাস্টম deserializers এবং validators তৈরি করে আরও জটিল validation নিয়ম প্রয়োগ করা সম্ভব।
- Nested Validation:
@Validannotations ব্যবহার করে nested objects validate করা যায়। - Error Handling: Jackson validation errors সহজেই রিপোর্ট করা যায়।
এই পদ্ধতিগুলো ব্যবহার করে জটিল validation scenarios Jackson-এর মাধ্যমে দক্ষতার সাথে হ্যান্ডল করা সম্ভব।
Read more